//
//  uiFactory.hpp
//  smu_test1
//
//  Created by jiayi on 2016/10/2.
//
//

#ifndef uiFactory_hpp
#define uiFactory_hpp

class uiFactoryItem
{
public:
    uiFactoryItem() : _free( true ){}
    virtual ~uiFactoryItem(){}
    
    void setFree( bool free ){ _free = free; }
    bool isFree() const { return _free; }
    
    virtual void deleteFactoryItem() = 0;
    
protected:
    bool _free;
};

template< class T >
class uiFactory
{
public:
    typedef list<T*> Ts;
    typedef typename Ts::iterator TsIter;
    typedef typename Ts::const_iterator TsConstIter;
    
public:
    static uiFactory<T>& getInstance(){
        static uiFactory<T> s;
        return s;
    }
    
    ~uiFactory();
    
public:
    T* getObject();
    void deleteObject( T* object );
    
protected:
    uiFactory(){}
    
protected:
    Ts _container;
    
};


template<class T>
uiFactory<T>::~uiFactory()
{
    typename uiFactory<T>::TsIter iter = _container.begin();
    for( ; iter != _container.end(); ++ iter ){
        (*iter)->release();
    }
    _container.clear();
}


template<class T>
T* uiFactory<T>::getObject()
{
    
    T* back = _container.back();
    
    if( !back || !back->isFree() ){
        // do not have free object, create a new one
        T* newT = T::create();
        newT->retain();
        _container.push_front( newT );
        back = newT;
    }
    back->setFree(false);
    return back;
}

template<class T>
void uiFactory<T>::deleteObject( T* object )
{
    if( !object ){
        return;
    }
    
    object->setFree( true );
    object->deleteFactoryItem();
    object->retain();
    _container.remove( object );
    // push free object to the end of container
    _container.push_back( object );
    object->release();
}

#endif /* uiFactory_hpp */
